﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KNN
{
    class KNN_R:KNN_C
    {
        double _M;
        public KNN_R(string path):base(path)//otwiera plik i zczytuje dane(potem i tak bedzie baza danych sql)
        {
            _M = 0.01;
        }
        public double Create(int quantity, int k, double m) //tworzy liste dokladnosci dla danego procenta, procent oznacza ilsoc uczacych 
        {
            _QuantityOfTester = quantity;
            _K = k;
            _M = m;
            double precision = 0;
            Shuffling();
            Neighbour[][] neighbour = new Neighbour[_QuantityOfTester][];
            for (int tester = 0; tester < _QuantityOfTester; tester++)
                neighbour[tester] = FindNearestNeighbors(tester);//glowna funkcja, znajdujemy oraz przyporzadkowujemy <ilosc_najblizszych> testowych

            for (int tester = 0; tester < _QuantityOfTester; tester++)
            {
                double a = 0;
                double weight = 0;
                double Yi = 0;
                for (int i = 0; i < _K; i++)
                    a += neighbour[tester][i].Distance;
                a /= _K;
                a *= _M;
                for (int i = 0; i < _K; i++)
                {
                    int index = neighbour[tester][i].Index;
                    Yi += _Y[index] * (1 / neighbour[tester][i].Distance + a);
                    weight += 1 / (neighbour[tester][i].Distance + a); 
                }
                Yi /= weight;
                precision += Math.Pow(Yi - _Y[tester], 2);
                //Console.WriteLine("Numer testowego     :" + tester);
                //Console.WriteLine("Klasa testowego     :" + _Class[tester]);
                //Console.WriteLine("x1                  :" + _Vector[tester][0]);
                //Console.WriteLine("x2                  :" + _Vector[tester][1]);
                //Console.WriteLine("x3                  :" + _Vector[tester][2]);
                //Console.WriteLine("x4                  :" + _Vector[tester][3]);
                //Console.WriteLine("--------------------------------");
                
            }
            //Console.WriteLine("Dokladnosc:::>>>:::" + precision/_QuantityOfTester);
            precision /= _QuantityOfTester;
            Math.Pow(precision, 0.5);

            return precision;
        }
        new public double Create(int quantity, int k) //tworzy liste dokladnosci dla danego procenta, procent oznacza ilsoc uczacych 
        {
            _QuantityOfTester = quantity;
            _K = k;
            double precision = 0;
            Shuffling();
            Neighbour[][] neighbour = new Neighbour[_QuantityOfTester][];
            for (int tester = 0; tester < _QuantityOfTester; tester++)
                neighbour[tester] = FindNearestNeighbors(tester);//glowna funkcja, znajdujemy oraz przyporzadkowujemy <ilosc_najblizszych> testowych

            for (int tester = 0; tester < _QuantityOfTester; tester++)
            {
                double a = 0;
                double weight = 0;
                double Yi = 0;
                for (int i = 0; i < _K; i++)
                    a += neighbour[tester][i].Distance;
                a /= _K;
                a *= _M;
                for (int i = 0; i < _K; i++)
                {
                    int index = neighbour[tester][i].Index;
                    Yi += _Y[index] * (1 / neighbour[tester][i].Distance + a);
                    weight += 1 / (neighbour[tester][i].Distance + a);
                }
                Yi /= weight;
                precision += Math.Pow(Yi - _Y[tester], 2);
                //Console.WriteLine("Numer testowego     :" + tester);
                //Console.WriteLine("Klasa testowego     :" + _Class[tester]);
                //Console.WriteLine("x1                  :" + _Vector[tester][0]);
                //Console.WriteLine("x2                  :" + _Vector[tester][1]);
                //Console.WriteLine("x3                  :" + _Vector[tester][2]);
                //Console.WriteLine("x4                  :" + _Vector[tester][3]);
                //Console.WriteLine("--------------------------------");

            }
            //Console.WriteLine("Dokladnosc:::>>>:::" + precision/_QuantityOfTester);
            precision /= _QuantityOfTester;
            Math.Pow(precision, 0.5);

            return precision;
        }
        new public double[] Create(bool[,] AG_Table)//tworzy tablice precyzji 
        {
            if (AG_Table.GetLength(1) == _QuantityOfTester)
            {
                double[] precision = new double[AG_Table.GetLength(0)];
                Neighbour[][] neighbour = new Neighbour[_QuantityOfTester][];
                int length;
                for (int i = 0; i < AG_Table.GetLength(0); i++)
                {
                    length = 0;
                    for (int j = 0; j < AG_Table.GetLength(1); j++)
                        if (AG_Table[i, j] == true)
                        {
                            neighbour[j] = FindNearestNeighbors(j);
                            length++;
                        }
                    precision[i] = 0;
                    for (int j = 0; j < AG_Table.GetLength(1); j++)
                        if (AG_Table[i, j] == true)
                        {
                            /*
                             * 
                             */
                            double a = 0;
                            double weight = 0;
                            double Yi = 0;
                            for (int l = 0; l < _K; l++)
                                a += neighbour[j][l].Distance;
                            a /= _K;
                            a *= _M;
                            for (int k = 0; k < _K; k++)
                            {
                                int index = neighbour[j][k].Index;
                                Yi += _Y[index] * (1 / neighbour[j][k].Distance + a);
                                weight += 1 / (neighbour[j][k].Distance + a);
                            }
                            Yi /= weight;
                            precision[i] += Math.Pow(Yi - _Y[j], 2);
                            /*
                             * 
                             */ 
                        }
                    precision[i] /= length;
                    Math.Pow(precision[i], 0.5);

                }
                return precision;
            }
            else
            {
                Console.WriteLine("Bledna ilosc testowych");
                Console.ReadKey();
            }
            return null;
        }
        public double a
        {
            get { return _M; }
        }
    }
}
